package mil.af.amc.adpetracker.model;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.CollectionOfElements;

import javax.persistence.*;
import java.io.Serializable;
import java.util.*;

/**
 * Represents a Single ADPE Account, which has a primary custodian, >=1 alt custodians, and equipment assigned
 * to it.
 *
 * @author TSgt Jason Ferguson
 */

@Entity
@Cache(usage= CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Table(name = "T_ADPEACCOUNT")
public class AdpeAccount implements Serializable, Comparable, MappableEntity {

    private int id;
    private DRA dra;
    private String name;
    private Set<AccountAdpeAccount> accountSet = new HashSet<AccountAdpeAccount>();
    //private Set<Account> accountSet = new HashSet<Account>();
    private Set<User> primaryCustodian = new HashSet<User>();
    private Set<User> alternateCustodians = new TreeSet<User>();
    private Set<EquipmentItem> accountInventory = new TreeSet<EquipmentItem>();
    //private Organization organization;
    private String organization;

    public AdpeAccount() {

    }

    public AdpeAccount(String name, DRA dra) {
        this.name = name;
        this.dra = dra;
    }

    @Id
    @Column(name = "ACCOUNTID")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ACCOUNTID_SEQ")
    @SequenceGenerator(name = "ACCOUNTID_SEQ", sequenceName = "S_ADPEACCOUNT")
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @ManyToOne
    @JoinColumn(name = "DRAID")
    public DRA getDra() {
        return dra;
    }

    public void setDra(DRA dra) {
        this.dra = dra;
    }

    @Column(name = "ACCOUNTNAME")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

//    @ManyToMany
//    @JoinTable(name="T_ACCT_ADPEACCT",
//        joinColumns=@JoinColumn(name="ADPEACCTID"),
//        inverseJoinColumns = @JoinColumn(name="ACCTID"))
//    //@AttributeOverride(name="custodianType", column = @Column(name="TYPE"))
//    public Set<Account> getAccountSet() {
//        return accountSet;
//    }
//
//    public void setAccountSet(Set<Account> accountSet) {
//        this.accountSet = accountSet;
//    }

    @CollectionOfElements
    public Set<AccountAdpeAccount> getAccountSet() {
        return accountSet;
    }

    public void setAccountSet(Set<AccountAdpeAccount> accountSet) {
        this.accountSet = accountSet;
    }

    @OneToMany
    @JoinTable(name = "T_PRIMARYCUSTODIANS",
            joinColumns = {@JoinColumn(name = "ADPEACCOUNTID")},
            inverseJoinColumns = {@JoinColumn(name = "PCUSTODIANID")})
    public Set<User> getPrimaryCustodian() {
        return primaryCustodian;
    }

    public void setPrimaryCustodian(Set<User> primaryCustodian) {
        this.primaryCustodian = primaryCustodian;
    }

    @OneToMany
    @JoinTable(name = "T_ACCOUNT_ALTCUSTODIANS_LINK",
            joinColumns = {@JoinColumn(name = "ADPEACCOUNTID")},
            inverseJoinColumns = {@JoinColumn(name = "CUSTODIANID")})
    public Set<User> getAlternateCustodians() {
        return alternateCustodians;
    }

    public void setAlternateCustodians(Set<User> alternateCustodians) {
        this.alternateCustodians = alternateCustodians;
    }


    @OneToMany(mappedBy="account")
    @Cache(usage= CacheConcurrencyStrategy.READ_WRITE)
    public Set<EquipmentItem> getAccountInventory() {
        return accountInventory;
    }

    public void setAccountInventory(Set<EquipmentItem> accountInventory) {
        this.accountInventory = accountInventory;
    }

    @Column(name="ORGANIZATIONNAME", length = 20)
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    public String getOrganization() {
        return organization;
    }

    public void setOrganization(String organization) {
        this.organization = organization;
    }

    public int compareTo(Object o) {
        String o1 = this.getName();
        String o2 = (((AdpeAccount) o).getName());

        return o1.compareTo(o2);
    }

    @SuppressWarnings({"unchecked"})
    public Map toMap() {

        Map results = new HashMap();
        results.put("id", this.getId());
        results.put("name", this.getName());
        results.put("organization", this.getOrganization());

        return results;
    }
}
